﻿using Coding4Fun.AppsListControl;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace AppsListControl.Shared
{
    public class MarketplaceUpdater
    {
        private const string NS_ATOM = "http://www.w3.org/2005/Atom";
        private const string NS_ZUNE = "http://schemas.zune.net/catalog/apps/2008/02";

        public MarketplaceUpdater ()
	    {
            Apps = new List<MarketplaceApp>();
            CountryCode = Thread.CurrentThread.CurrentCulture.Name;
            FreeTranslation = "Free";
            MarketplaceRoot = "http://marketplaceedgeservice.windowsphone.com";
	    }

        public List<MarketplaceApp> Apps { get; set; }
        public string FreeTranslation { get; set; }
        public string MarketplaceRoot { get; set; }
        public string PublisherName { get; set; }
        public Version OSVersion { get; set; }
        public DateTime LastUpdate { get; set; }
        public string CountryCode { get; set; }

        public async Task<bool> UpdateMarketplaceApps()
        {
            var newApps = new List<MarketplaceApp>();

            // If we already have apps, see how old they are
            if (Apps != null && Apps.Count() > 0)
            {
#if DEBUG
                // In debug mode, always load
#else
                // Use the cache if within a day...
                if (DateTime.Now.Subtract(LastUpdate).TotalDays < 1)
                {
                    return false;
                }
#endif
            }

            var c = new HttpClient();

            try
            {
                string storeVersion = "7.1";
                if (OSVersion.Major == 8) storeVersion = "8.0";

                var url = new Uri(MarketplaceRoot + "/v3.2/" + CountryCode + "/apps?publisher=" + PublisherName + "&orderBy=Title&store=Zest&clientType=WinMobile+" + storeVersion);
                while (url != null)
                {
                    var result = await c.GetAsync(url);
                    if (result.IsSuccessStatusCode)
                    {
                        var data = await result.Content.ReadAsStringAsync();
                        url = ParseItemFeed(data, newApps);
                    }
                }

                Apps = newApps.OrderBy(a => a.Title).ToList();
                return true;
            }
            catch
            {
                return false;
            }
        }

        private Uri ParseItemFeed(string xml, IList<MarketplaceApp> apps)
        {
            var doc = XDocument.Parse(xml);
            var feed = doc.Element(XName.Get("feed", NS_ATOM));

            foreach (var item in feed.Elements(XName.Get("entry", NS_ATOM)))
            {
                var id = item.Element(XName.Get("id", NS_ATOM)).Value.Split(':')[2];

                var app = new MarketplaceApp();
                app.Id = id;
                app.AppLink = "http://windowsphone.com/s?appid=" + id;
                app.Title = (string)item.Element(XName.Get("title", NS_ATOM));
                //app.ShortDescription = (string)item.Element(XName.Get("title", NS_ATOM));
                app.UserRatingCount = (int)item.Element(XName.Get("userRatingCount", NS_ZUNE));
                app.Version = (string)item.Element(XName.Get("version", NS_ZUNE));
                app.AverageUserRating = (double)item.Element(XName.Get("averageUserRating", NS_ZUNE)) / 2.0;
                app.ReleaseDate = ((DateTime)item.Element(XName.Get("releaseDate", NS_ZUNE))).ToString("d");
                app.PrimaryImageUrl = MarketplaceRoot + "/v3.2/" + CountryCode + "/apps/" + id + "/primaryImage?width=95&height=95&resize=true";

                var offers = item.Element(XName.Get("offers", NS_ZUNE)).Elements(XName.Get("offer", NS_ZUNE));//.Where(o => (string)o.Element(XName.Get("priceCurrencyCode", NS_ZUNE)) == DesiredCurrencyCode);
                var trial = offers.FirstOrDefault(o => (string)o.Element(XName.Get("licenseRight", NS_ZUNE)) == "Trial");
                var paid = offers.FirstOrDefault(o => (string)o.Element(XName.Get("licenseRight", NS_ZUNE)) != "Trial"); // Purchase.  Any more?  I've only seen two...

                if (trial != null)
                {
                    app.DisplayPrice = FreeTranslation;
                }
                else if( paid != null )
                {
                    var p = (double)paid.Element(XName.Get("price", NS_ZUNE));
                    if( p > 0 )
                        app.DisplayPrice = (string)paid.Element(XName.Get("displayPrice", NS_ZUNE));
                    else
                        app.DisplayPrice = FreeTranslation;

                    app.PriceCurrencyCode = (string)paid.Element(XName.Get("priceCurrencyCode", NS_ZUNE));
                }

                string t = app.Title;
                var next = apps.FirstOrDefault(a => string.Compare(a.Title, t) == 1);
                int idx = (next == null) ? 0 : apps.IndexOf(next);
                apps.Insert(idx, app);
            }

            var link = feed.Elements(XName.Get("link", NS_ATOM)).FirstOrDefault(l => (string)l.Attribute("rel") == "next");
            if (link != null)
            {
                return new Uri(MarketplaceRoot + (string)link.Attribute("href"));
            }

            return null;
        }
    }
}
